/*
 * @(#)CompileUtil.java
 * 2011-8-11 下午11:31:10
 *
 * Copyright (c) 2018-2028, HangZhou QiYun InfoTech Co.,Ltd. .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qyxx.platform.gsc.parse;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


/**
 *  动态编译工具类
 *  @author gxj
 *  @version 1.0
 *  @since 1.6 2011-8-11 下午11:31:10
 */

public class CompileUtil {

    private static List<File> sourceList = new ArrayList<File>(); //源文件列表    
    
    public static synchronized void defaultCompile(String basePath)throws Exception{
        File f = new File(basePath);
        String sourcePath = f.getAbsolutePath()+File.separator+"src";
        String targetPath = f.getAbsolutePath()+File.separator+"bin";
        String libPath = f.getAbsolutePath()+File.separator+"lib";
        compilePackage(sourcePath,targetPath,libPath);
    }
    

    /**
     * 编译包及其子包
     * @param sourcePath String
     * @param targetPath String 编译后的类文件的输出文件夹
     * @param libPath String 放置第三方类库的文件夹
     * @throws Exception
     */
	public static synchronized boolean compilePackage(
			String sourcePath, String targetPath, String libPath)throws Exception{
        sourceList.clear();
        return compileSourceFile(getSourceList(sourcePath),targetPath,libPath);
    }
    
    private static List<File> getSourceList(String dirPath)throws Exception{
        
        File dir = new File(dirPath);
        File[] files = dir.listFiles(new DefaultFilenameFilter("java"));
        for(File f:files){
            if(f.isDirectory()){//如果是文件夹则迭代 
                getSourceList(dirPath+File.separator+f.getName());
            }else{
                sourceList.add(f);
            }
        }
        return sourceList;
    }
    
    /**
     * 编译单个Java源文件
     * @param fileName String
     * @param targetPath String
     * @param libPath String
     */
    public static boolean compileSourceFile(final String fileName , String targetPath , String libPath){
    	boolean flag = true;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        try {
            Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjects(fileName);
            flag = compiler.getTask(null, fileManager, null, getCompileOptions(targetPath,libPath), null, sourcefiles).call();
            fileManager.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        return flag;
    }
    
    /**
     * @param files List<File>
     * @param targetPath String 目标文件夹
     * @param libPath String 放置第三方类库的文件夹
     */
    private static boolean compileSourceFile(List<File> files , String targetPath , String libPath){
    	boolean flag = true;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        try {
            Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjectsFromFiles(files);
            flag = compiler.getTask(null, fileManager, null, getCompileOptions(targetPath,libPath), null, sourcefiles).call();
            fileManager.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        return flag;
    }
    
    /**
     * 设置编译选项
     * @param targetPath String
     * @param libPath String
     * @return
     */
    private static Iterable<String> getCompileOptions(String targetPath , String libPath){
        List<String> options = new ArrayList<String>();
        
        //设置编译后生成的类文件的输出目录
        if(targetPath != null){
            options.add("-d");
            options.add(targetPath);
        }
        
        //设置用到的第三方类库的目录
        if(libPath != null){
            options.add("-classpath");
            options.add(getLibStr(libPath));
        } else {
        	options.add("-classpath");
        	StringBuilder sb = new StringBuilder();
        	URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
        	for (URL url : urlClassLoader.getURLs())
        	    sb.append(url.getFile()).append(File.pathSeparator);
        	System.out.println(sb.toString());
        	options.add(sb.toString());
        }
        return options;
    }
    
    private static String getLibStr(String libPath){
        StringBuffer sb = new StringBuffer();
        File libDir = new File(libPath);
        File[] jarFiles = libDir.listFiles(new DefaultFilenameFilter("jar"));
        for(File f:jarFiles){
            if(!f.isDirectory()){
                sb.append(libPath+File.separator+f.getName()+";"); //多个jar文件用分号隔开
            }
        }
        return sb.substring(0, sb.lastIndexOf(";"));
    }
}
